﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.BusinessData.SystemSpecific;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.Runtime;
using System.Diagnostics;
using System.IO.Packaging;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Client;

namespace TFSCustomConnector
{
    public class AttachHelper
    {
        static string Identifier = "System123Id";
        static string WIIdentifier = "WI123System123Id";
        static string WIWASLink = "WI123Hyperlink";

        static string Log(string source, string message, string clsNamespace, string wiType)
        {
            string formattedmessage = string.Format("LobSystem: {0}, Entity: {1}, Source: {2}, Message: {3}", clsNamespace, wiType, source, message);

            if (!EventLog.SourceExists(clsNamespace))
                EventLog.CreateEventSource(clsNamespace, "Application");

            var flag = (source.Contains("error") ? EventLogEntryType.Error : EventLogEntryType.Information);

            EventLog.WriteEntry(clsNamespace, formattedmessage, flag);

            return formattedmessage;
        }

        static WorkItemStore ConnectToTFS(string TFSConnectionURL, string clsNamespace, string wiType)
        {
            TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(TFSConnectionURL));
            var wistore = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));

            //Log("ConnectToTFS", TFSConnectionURL, clsNamespace, wiType);
            if (wistore == null) throw new Exception("wistore == null");

            return wistore;
        }

        internal static DynamicType[] QueryAttachments(DynamicType template, string TfsConnURL, string filter, string clsNamespace, string wiType)
        {
            var dynItemColl = new List<DynamicType>();

            WorkItemStore wistore = ConnectToTFS(TfsConnURL, clsNamespace, wiType);
            var wicoll = wistore.Query(filter);
            //Log("QueryWorkItems", wicoll.Count + "==>" + filter, clsNamespace, wiType);

            foreach (WorkItem wi in wicoll)
            {
                //Log("QueryWorkItems", wi.Id.ToString(), clsNamespace, wiType);
                foreach (Attachment itm in wi.Attachments)
                {
                    dynItemColl.Add(FillDynamicItem(template, wi.Id, itm));
                }
            }

            return dynItemColl.ToArray();
        }

        internal static DynamicType FindAttachment(DynamicType template, string TfsConnURL, string ID, string clsNamespace, string wiType)
        {
            WorkItemStore wistore = ConnectToTFS(TfsConnURL, clsNamespace, wiType);

            int wiID = int.Parse(ID.Substring(0, ID.IndexOf('-')));
            string name = ID.Substring(ID.IndexOf('-') + 1);          
            var wi = wistore.GetWorkItem(wiID);
            //Log("FindWorkItem", ID.ToString(), clsNamespace, wiType);

            Attachment attach = null;
            attach = wi.Attachments.Cast<Attachment>().FirstOrDefault(x => x.Name == name);

            return FillDynamicItem(template, wi.Id, attach);
        }

        internal static void DeleteAttachment(string TfsConnURL, string ID, string clsNamespace, string wiType)
        {
            //Log("DestroyWorkItem", ID.ToString(), clsNamespace, wiType);

            WorkItemStore wistore = ConnectToTFS(TfsConnURL, clsNamespace, wiType);
            int wiID = int.Parse(ID.Substring(0, ID.IndexOf('-')));
            string name = ID.Substring(ID.IndexOf('-') + 1);
            var dt = new DynamicType();

            var wi = wistore.GetWorkItem(wiID);
            //Log("FindWorkItem", ID.ToString(), clsNamespace, wiType);

            Attachment attach = null;
            attach = wi.Attachments.Cast<Attachment>().FirstOrDefault(x => x.Name == name);

            if (attach != null)
                wi.Attachments.Remove(attach);
            else
                throw new Exception("Attachment cannot be deleted. WI.Id="+wiID+", File Name="+name);
        }

        internal static System.IO.Stream DownloadAttachment(string TfsConnURL, string ID, string clsNamespace, string wiType)
        {
            WorkItemStore wistore = ConnectToTFS(TfsConnURL, clsNamespace, wiType);

            int wiID = int.Parse(ID.Substring(0, ID.IndexOf('-')));
            string name = ID.Substring(ID.IndexOf('-') + 1);
            var dt = new DynamicType();

            var wi = wistore.GetWorkItem(wiID);
            //Log("FindWorkItem", ID.ToString(), clsNamespace, wiType);

            Attachment attach = null;
            attach = wi.Attachments.Cast<Attachment>().FirstOrDefault(x => x.Name == name);

            if (attach != null)
            {
                //return System.IO.File.OpenRead(attach.Uri.ToString());
                System.Net.WebClient request = new System.Net.WebClient();                    
                request.Credentials = System.Net.CredentialCache.DefaultCredentials;
                return request.OpenRead(attach.Uri);
            }
            else
                return null;
        }

        internal static DynamicType[] FindAssociations(DynamicType template, string TfsConnURL, int ID, string clsNamespace, string wiType)
        {
            var dynItemColl = new List<DynamicType>();

            WorkItemStore wistore = ConnectToTFS(TfsConnURL, clsNamespace, wiType);
            var wi = wistore.GetWorkItem(ID);
            //Log("QueryWorkItems", wicoll.Count + "==>" + filter, clsNamespace, wiType);

            foreach (Attachment itm in wi.Attachments)
            {
                dynItemColl.Add(FillDynamicItem(template, wi.Id, itm));
            }

            return dynItemColl.ToArray();
        }

        internal static DynamicType FillDynamicItem(DynamicType template, int wiid, Attachment attach)
        {
            var dt = new DynamicType();
            if (template.Any(x => x.Key == Identifier)) dt.Add(Identifier, wiid + "-" + attach.Name);
            if (template.Any(x => x.Key == WIIdentifier)) dt.Add(WIIdentifier, wiid);
            if (template.Any(x => x.Key == WIWASLink))
            {
                object value = null;
                if (attach != null) value = attach.Uri.ToString()+", "+attach.Name;

                dt.Add(WIWASLink, value);
            }

            foreach (var propinfo in typeof(Attachment).GetProperties())
            {
                if (!template.Any(x => x.Key == propinfo.Name)) continue;

                object value = null;
                if (attach != null)
                {
                    value = propinfo.GetValue(attach, null);
                    if (value is System.Uri && value != null) value = value.ToString();
                }

                dt.Add(propinfo.Name, value);
            }

            return dt;
        }
    }
}
